1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package com.google.common.collect;
16
17 import static com.google.common.base.Preconditions.checkArgument;
18 import static com.google.common.base.Preconditions.checkNotNull;
19 import static com.google.common.collect.BoundType.CLOSED;
20
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23
24 import java.io.Serializable;
25 import java.util.Collection;
26
27 import javax.annotation.Nullable;
28
29
30
31
32
33
34 @GwtCompatible(emulated = true)
35 @SuppressWarnings("unchecked")
36 final class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C> {
37 private final Range<C> range;
38
39 RegularContiguousSet(Range<C> range, DiscreteDomain<C> domain) {
40 super(domain);
41 this.range = range;
42 }
43
44 private ContiguousSet<C> intersectionInCurrentDomain(Range<C> other) {
45 return (range.isConnected(other))
46 ? ContiguousSet.create(range.intersection(other), domain)
47 : new EmptyContiguousSet<C>(domain);
48 }
49
50 @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
51 return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive)));
52 }
53
54 @Override ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
55 boolean toInclusive) {
56 if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) {
57
58 return new EmptyContiguousSet<C>(domain);
59 }
60 return intersectionInCurrentDomain(Range.range(
61 fromElement, BoundType.forBoolean(fromInclusive),
62 toElement, BoundType.forBoolean(toInclusive)));
63 }
64
65 @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
66 return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive)));
67 }
68
69 @GwtIncompatible("not used by GWT emulation")
70 @Override int indexOf(Object target) {
71 return contains(target) ? (int) domain.distance(first(), (C) target) : -1;
72 }
73
74 @Override public UnmodifiableIterator<C> iterator() {
75 return new AbstractSequentialIterator<C>(first()) {
76 final C last = last();
77
78 @Override
79 protected C computeNext(C previous) {
80 return equalsOrThrow(previous, last) ? null : domain.next(previous);
81 }
82 };
83 }
84
85 @GwtIncompatible("NavigableSet")
86 @Override public UnmodifiableIterator<C> descendingIterator() {
87 return new AbstractSequentialIterator<C>(last()) {
88 final C first = first();
89
90 @Override
91 protected C computeNext(C previous) {
92 return equalsOrThrow(previous, first) ? null : domain.previous(previous);
93 }
94 };
95 }
96
97 private static boolean equalsOrThrow(Comparable<?> left, @Nullable Comparable<?> right) {
98 return right != null && Range.compareOrThrow(left, right) == 0;
99 }
100
101 @Override boolean isPartialView() {
102 return false;
103 }
104
105 @Override public C first() {
106 return range.lowerBound.leastValueAbove(domain);
107 }
108
109 @Override public C last() {
110 return range.upperBound.greatestValueBelow(domain);
111 }
112
113 @Override public int size() {
114 long distance = domain.distance(first(), last());
115 return (distance >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) distance + 1;
116 }
117
118 @Override public boolean contains(@Nullable Object object) {
119 if (object == null) {
120 return false;
121 }
122 try {
123 return range.contains((C) object);
124 } catch (ClassCastException e) {
125 return false;
126 }
127 }
128
129 @Override public boolean containsAll(Collection<?> targets) {
130 return Collections2.containsAllImpl(this, targets);
131 }
132
133 @Override public boolean isEmpty() {
134 return false;
135 }
136
137 @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
138 checkNotNull(other);
139 checkArgument(this.domain.equals(other.domain));
140 if (other.isEmpty()) {
141 return other;
142 } else {
143 C lowerEndpoint = Ordering.natural().max(this.first(), other.first());
144 C upperEndpoint = Ordering.natural().min(this.last(), other.last());
145 return (lowerEndpoint.compareTo(upperEndpoint) < 0)
146 ? ContiguousSet.create(Range.closed(lowerEndpoint, upperEndpoint), domain)
147 : new EmptyContiguousSet<C>(domain);
148 }
149 }
150
151 @Override public Range<C> range() {
152 return range(CLOSED, CLOSED);
153 }
154
155 @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
156 return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain),
157 range.upperBound.withUpperBoundType(upperBoundType, domain));
158 }
159
160 @Override public boolean equals(@Nullable Object object) {
161 if (object == this) {
162 return true;
163 } else if (object instanceof RegularContiguousSet) {
164 RegularContiguousSet<?> that = (RegularContiguousSet<?>) object;
165 if (this.domain.equals(that.domain)) {
166 return this.first().equals(that.first())
167 && this.last().equals(that.last());
168 }
169 }
170 return super.equals(object);
171 }
172
173
174 @Override public int hashCode() {
175 return Sets.hashCodeImpl(this);
176 }
177
178 @GwtIncompatible("serialization")
179 private static final class SerializedForm<C extends Comparable> implements Serializable {
180 final Range<C> range;
181 final DiscreteDomain<C> domain;
182
183 private SerializedForm(Range<C> range, DiscreteDomain<C> domain) {
184 this.range = range;
185 this.domain = domain;
186 }
187
188 private Object readResolve() {
189 return new RegularContiguousSet<C>(range, domain);
190 }
191 }
192
193 @GwtIncompatible("serialization")
194 @Override Object writeReplace() {
195 return new SerializedForm<C>(range, domain);
196 }
197
198 private static final long serialVersionUID = 0;
199 }